package com.bckj.fastboot.upms.biz.core.perm;

import MathBasic.Managements.Data.BinarySet;
import com.bckj.fastboot.upms.api.dto.PermsCreateParams;
import lombok.Getter;

import java.util.HashMap;
import java.util.Map;

/**
 * Permissions
 *
 * @author wfc
 * @since 2021-09-28
 */
public class Perms {
    private final Map<Integer, BinarySet> permissionsMap;
    //0角色1用户
    @Getter
    private final int type;
    @Getter
    private final Long id;
    //权限类型 0权限 1展示
    @Getter
    private final int permsType;

    private static final long DEFAULT_FACTOR = 6148914691236517205L;

    public static BinarySet getDefBinarySet() {
        BinarySet bs = new BinarySet();
        bs.set_Factor(DEFAULT_FACTOR);
        return bs;
    }

    public Map<Integer, BinarySet> getPermissionsMap() {
        return permissionsMap;
    }

    public Perms(PermsCreateParams params) {
        this(params.getId(), params.getType(), params.getPermsType());
    }

    public Perms(Long id, int type, int permsType) {
        this.permissionsMap = new HashMap<>();
        this.id = id;
        this.type = type;
        this.permsType = permsType;
    }


    public void setPermissions(int keyIndex, long data, long filter) {
        BinarySet value = this.permissionsMap.get(keyIndex);
        if (value == null) {
            this.permissionsMap.put(keyIndex, new BinarySet(DEFAULT_FACTOR, data, filter));
        } else {
            value.Inject(data, false);
            value.InjectFilter(filter, false);
            this.permissionsMap.put(keyIndex, value);
        }
    }

    public BinarySet getPermissionByKeyIndex(int keyIndex) {
        return this.permissionsMap.computeIfAbsent(keyIndex, k -> getDefBinarySet());
    }

    public void injectByKeyIndex(int keyIndex, int bitLocation) {
        BinarySet set = this.getPermissionByKeyIndex(keyIndex);
        set.InjectByOrdinal(bitLocation);
        this.permissionsMap.put(keyIndex, set);
    }

    public void injectFilterByKeyIndex(int keyIndex, int bitLocation) {
        BinarySet set = this.getPermissionByKeyIndex(keyIndex);
        set.InjectFilterByOrdinal(bitLocation);
        this.permissionsMap.put(keyIndex, set);
    }

    public void removeByKeyIndex(int keyIndex, int bitLocation) {
        BinarySet set = this.getPermissionByKeyIndex(keyIndex);
        set.RejectByOrdinal(bitLocation);
        this.permissionsMap.put(keyIndex, set);
    }

    public void removeFilterByKeyIndex(int keyIndex, int bitLocation) {
        BinarySet set = this.getPermissionByKeyIndex(keyIndex);
        set.RejectFilterByOrdinal(bitLocation);
        this.permissionsMap.put(keyIndex, set);
    }

    public Boolean verifyPermissionByKeyIndex(int keyIndex) {
        Object value = this.permissionsMap.get(keyIndex);
        return value != null;
    }

    public Boolean verify(int keyIndex, int bitLocation) {
        int location = (bitLocation - 1) % BinarySet.SupportedLength;
        keyIndex = keyIndex + (bitLocation - 1) / BinarySet.SupportedLength;
        BinarySet value = this.permissionsMap.get(keyIndex);
        if (value != null) {
            return value.VerifyByOrdinal(location + 1);
        } else {
            return false;
        }
    }
}
